﻿using MotionControl.Core.Mvvm;
using MotionControl.Services.Interfaces;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using System.Collections.ObjectModel;
using MotionControl.Core;
using Prism.Ioc;
using System.Diagnostics;
using MotionControl.Modules.RestService.business;
using Newtonsoft.Json;
using System.Collections.Generic;
using System;
using System.IO;
using System.Security.Policy;
using Newtonsoft.Json.Linq;
using System.Diagnostics.Eventing.Reader;
using System.Windows.Threading;
using NLog;
using System.Linq;
using NLog.LayoutRenderers.Wrappers;
using Microsoft.AspNetCore.Mvc.Formatters;
using System.Windows.Interop;
using System.Data.SqlTypes;
using System.Windows.Controls;
using System.Runtime.CompilerServices;
//using Microsoft.Extensions.Logging;


namespace MotionControl.Modules.RestService.ViewModels
{
    [JsonObject(MemberSerialization.OptIn)]
    public class RestServiceViewModel : RegionViewModelBase
    {
        private readonly IEventAggregator _eventAgg;
        private readonly IContainerExtension _container;
        //private readonly RestService _restService;

        private string _message;
        public string Message
        {
            get { return _message; }
            set { SetProperty(ref _message, value); }
        }

        private string _url = "http://127.0.0.1:8888";
        private const string jsonFilePath = "data/restful.json";

        [JsonProperty]
        public string Url
        {
            get { return _url; }
            set { SetProperty(ref _url, value); }
        }

        [JsonProperty]
        public string SendText { get; set; } = "";

        private string _cmdStr = "";
        public string CmdStr
        {
            get { return _cmdStr; }
            set { SetProperty(ref _cmdStr, value);}
        }

        private ObservableCollection<ClientInfo> _clientList = new ObservableCollection<ClientInfo>();
    
        [JsonProperty]
        public ObservableCollection<ClientInfo> ClientList
        {
            get { return _clientList; }
            set { SetProperty(ref _clientList, value); }
        }

        public ClientInfo SelectedClient { get; set; }

        public ObservableCollection<string> UrlPaths { get; set; } = new
            ObservableCollection<string>(){ "plc","light"};

        [JsonProperty]
        public string SelectedPath { get; set; }

        public DelegateCommand SendCommand { get; private set; }
        public DelegateCommand RestartCommand { get; private set; }
        public DelegateCommand<object> SelectionChangedCommand { get; }
        public DelegateCommand AddClientCommand { get; set; }
        public DelegateCommand RemoveClientCommand { get; set; }
        public DelegateCommand ClearLogCommand { get; set; }

        private ClientInfo curClient = null;

        private ObservableCollection<string> _logMsgs = new ObservableCollection<string>();
        public ObservableCollection<string> LogMsgs
        {   get { return _logMsgs; }
            set { SetProperty(ref _logMsgs, value); }
        }

        private NLog.ILogger _loggers;
        public RestServiceViewModel(IContainerExtension container, IRegionManager regionManager, IMessageService messageService, IEventAggregator aggregator, ILogger logger) :
        base(regionManager)
        {
            _container = container;
            _eventAgg = aggregator;
            _loggers = logger;
            //_loggers.Fatal("test");

            //Message = messageService.GetMessage();
            ReadFromJsonFile();

            _eventAgg.GetEvent<MainWindowEvent>().Subscribe(OnMainWindowEvent);

            SendCommand = new DelegateCommand(OnSendCommand);
            RestartCommand = new DelegateCommand(OnRestartCommand);
            SelectionChangedCommand = new DelegateCommand<object>(OnSelectionChangedCommand);
            AddClientCommand = new DelegateCommand(OnAddClientCommand);
            RemoveClientCommand = new DelegateCommand(OnRemoveClientCommand);
            ClearLogCommand = new DelegateCommand(OnClearLogCommand);

            HttpService.GetInstance.Start(Url);
            HttpService.GetInstance.HttpMsgAction += OnHttpMsg;
            //HttpService.GetInstance.PLCMsgAction += OnPLCMsg;
            //HttpService.GetInstance.LightMsgAction += OnLightMsg;
            

        }
        private void OnSendCommand()
        {
            if (SelectedPath == "plc")
                OnPLCMsg("local",SendText);
            else if (SelectedPath == "light")
                OnLightMsg("local", SendText);
        }
        private void OnRestartCommand()
        {
            HttpService.GetInstance.AddEndpoint(Url);
        }
        private void OnClearLogCommand()
        {
            LogMsgs.Clear();
        }
        private void OnSelectionChangedCommand(object info) {
            curClient = new ClientInfo();
        }

        private void OnAddClientCommand()
        {
            ClientList.Add(new ClientInfo { Name = SelectedClient.Name, IP = SelectedClient.IP });
        }

        private void OnRemoveClientCommand()
        {
            ClientList.Remove(SelectedClient);
        }

        public void OnHttpMsg(string ip, string msg)
        {
            _loggers.Info(ip + ": " + msg);
            ShowMsg(LogLevel.Info, ip, msg);
            var clientMsg = JsonConvert.DeserializeObject<ClientMsg>(msg);
            if (clientMsg == null)
                return;
            var res = ClientList.ToList().Find( x => x.IP == ip);
            if (res == null)
            {
                ShowMsg(LogLevel.Warning, ip, "is not added!");
                return;
            }
            if (!res.IsSelected)
            {
                ShowMsg(LogLevel.Warning, ip, "is not choosed!");
                return;
            }

            if (clientMsg.PLCList != null)
            {
                foreach (var data in clientMsg.PLCList)
                {
                    var jsonStr = JsonConvert.SerializeObject(data);
                    _eventAgg.GetEvent<PLCMsgEvent>().Publish(jsonStr);
                }
            }

            if (clientMsg.LightList != null)
            {
                foreach (var data in clientMsg.LightList)
                {
                    var jsonStr = JsonConvert.SerializeObject(data);
                    _eventAgg.GetEvent<LightMsgEvent>().Publish(jsonStr);
                }
            }
        }
        public void OnPLCMsg(string ip, string cmd)
        {
            _loggers.Info(cmd);
            ShowMsg(LogLevel.Info, ip, "plc:" + cmd);
            _eventAgg.GetEvent<PLCMsgEvent>().Publish(cmd);
        }
        public void OnLightMsg(string ip, string cmd)
        {
            _loggers.Info(cmd);
            ShowMsg(LogLevel.Info, ip, "light:" + cmd);
            _eventAgg.GetEvent<LightMsgEvent>().Publish(cmd);
        }

        private enum LogLevel{ 
            Info,
            Warning,
            Error
        }

        private void ShowMsg(LogLevel lvl, string name, string msg)
        {
            if (LogMsgs.Count > 1500)
                LogMsgs.Clear();

            string showStr = string.Format("[{0}] [Time][{1}] [IP][{2}]: \r\n {3}", lvl.ToString(), DateTime.Now.ToString("HH:mm:ss"), name, msg);

            System.Windows.Application.Current.Dispatcher.Invoke(() =>
                    LogMsgs.Add(showStr));
        }

        void OnMainWindowEvent(string cmd)
        {
            if (cmd == "Closed")
                SaveToJsonFile();
        }
        private void ReadFromJsonFile()
        {
            try
            {
                string jsonFromFile = File.ReadAllText(jsonFilePath);
                var urlStr = (JObject)JsonConvert.DeserializeObject(jsonFromFile);
                Url = urlStr["Url"].ToString();
                SelectedPath = urlStr["SelectedPath"].ToString();
                SendText = urlStr["SendText"].ToString();
                var JList = JsonConvert.DeserializeObject<List<ClientInfo>>(urlStr["ClientList"].ToString());
                ClientList = new ObservableCollection<ClientInfo>(JList);
            }
            catch (Exception ex)
            {
                _loggers.Error("ReadFromJsonFile:" + ex);
            }
        }
        private void SaveToJsonFile()
        {
            try
            {
                string str = JsonConvert.SerializeObject(this, Formatting.Indented);
                File.WriteAllText(jsonFilePath, str);
            }
            catch (Exception ex)
            {
                _loggers.Error("SaveToJsonFile:" + ex);
            }
        }
    }
}
